package com.dingtalk.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.dingtalk.mapper.UserMapper;
import com.dingtalk.util.Config;
import com.dingtalk.vo.JiraVo;
import com.dingtalk.vo.User;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Title: CommentService
 * @Description: TODO
 * @Create 2022/10/8 11:23
 * @Author: Wang.Tonglin
 * @Contact: wang.tonglin@trs.com.cn
 * @Company: 成都拓尔思信息技术有限公司
 * @Department: 中台（Middle-End）
 */
@Service
@Slf4j
public class CommentService {

    @Resource
    private Config config;

    @Resource
    private JiraVo jiraVo;
    
    @Resource
    private UserMapper userMapper;

    public void sendMessage(HttpServletRequest request) throws IOException {
        //获取数据
        JSONObject data = getData(request);
        System.out.println(data);
        if (data != null) {
            //钩子发过来需要处理的问题类型
            //1.删除一个issue
            if ("jira:issue_deleted".equals(data.getString("webhookEvent"))) {
                jiraVo.setWebhookEvent(data.getString("webhookEvent").substring(5));
                jiraVo.setName(data.getJSONObject("user").getString("displayName"));
                jiraVo.setIssue(data.getJSONObject("issue").getString("key"));
                jiraVo.setSummary(data.getJSONObject("issue").getJSONObject("fields").getString("summary"));
                jiraVo.setProjectName(data.getJSONObject("issue").getJSONObject("fields").getJSONObject("project").get("name").toString());
                jiraVo.setProjectKey(data.getJSONObject("issue").getJSONObject("fields").getJSONObject("project").get("key").toString());
                OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
                markdown.setTitle("jira机器人");

                markdown.setText("#### " + jiraVo.getName() + "  " + jiraVo.getWebhookEvent() + "  " + jiraVo.getIssue() + "\n" +
                        "> [" + jiraVo.getSummary() + "](http://" + config.getAddress() + "/browse/" + ")\n\n");
                send(jiraVo, markdown);
            }
            //2.新增一个issue
            if ("jira:issue_created".equals(data.getString("webhookEvent"))) {
                jiraVo.setWebhookEvent(data.getString("webhookEvent").substring(5));
                jiraVo.setName(data.getJSONObject("user").getString("displayName"));
                jiraVo.setIssue(data.getJSONObject("issue").getString("key"));
                jiraVo.setSummary(data.getJSONObject("issue").getJSONObject("fields").getString("summary"));
                jiraVo.setProjectName(data.getJSONObject("issue").getJSONObject("fields").getJSONObject("project").get("name").toString());
                jiraVo.setProjectKey(data.getJSONObject("issue").getJSONObject("fields").getJSONObject("project").get("key").toString());
                OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
                markdown.setTitle("jira机器人");

                markdown.setText("#### " + jiraVo.getName() + "  " + jiraVo.getWebhookEvent() + "  " + jiraVo.getIssue() + "\n" +
                        "> [" + jiraVo.getSummary() + "](http://" + config.getAddress() + "/browse/" + jiraVo.getIssue() + ")\n\n");
                send(jiraVo, markdown);
            }
            //3.更新一个issue
            if ("jira:issue_updated".equals(data.getString("webhookEvent"))) {
                try {
                    data.getJSONObject("changelog");
                } catch (Exception e) {
                    log.info("这个数据不处理!");
                }
                String name = data.getJSONObject("user").getString("displayName");
                String issue = data.getJSONObject("issue").getString("key");
                String summary = data.getJSONObject("issue").getJSONObject("fields").getString("summary");
                Object o = data.getJSONObject("changelog").getJSONArray("items").get(0);
                Map<String, String> map = com.alibaba.fastjson.JSONObject.
                        parseObject(o.toString(), new TypeReference<Map<String, String>>() {
                        });
                System.out.println(map);

                String field = map.get("field");
                String toString = map.get("toString");
                jiraVo.setProjectName(data.getJSONObject("issue").getJSONObject("fields").getJSONObject("project").get("name").toString());
                jiraVo.setProjectKey(data.getJSONObject("issue").getJSONObject("fields").getJSONObject("project").get("key").toString());
                OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
                markdown.setTitle("jira机器人");

                markdown.setText("#### " + name + " changed  " + issue + "  " + field + " to 【" + toString + "】\n" +
                        "> [" + summary + "](http://" + config.getAddress() + "/browse/" + jiraVo.getIssue() + ")\n\n");
                send(jiraVo, markdown);
            }
            if (data.getString("webhookEvent").contains("comment")) {
                jiraVo.setWebhookEvent(data.getString("webhookEvent"));
                jiraVo.setComment(data.getJSONObject("comment").getString("body"));
                jiraVo.setName(data.getJSONObject("comment").getJSONObject("updateAuthor").getString("displayName"));

                //先得到comment的网址
                String self = data.getJSONObject("comment").getString("self");
                String url = StringUtils.substringBefore(self, "/comment");
                try {
                    String username = config.getUsername();
                    String password = config.getPassword();

                    HttpResponse<JsonNode> response = Unirest.get(url)
                            .basicAuth(username, password)
                            .header("Accept", "application/json")
                            .asJson();
                    JsonNode body = response.getBody();
                    JSONObject jsonObject = new JSONObject(Boolean.parseBoolean(body.toString()));

                    jiraVo.setIssue(jsonObject.getString("key"));
                    jiraVo.setSummary(jsonObject.getJSONObject("fields").getString("summary"));
                    jiraVo.setProjectName(jsonObject.getJSONObject("fields").getJSONObject("project").get("name").toString());
                    jiraVo.setProjectKey(jsonObject.getJSONObject("fields").getJSONObject("project").get("key").toString());
                } catch (UnirestException e) {
                    e.printStackTrace();
                }

                OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
                markdown.setTitle("jira机器人");

                markdown.setText("#### " + jiraVo.getName() + "  " + jiraVo.getWebhookEvent() + "  " + jiraVo.getIssue() + "\n" +
                        "> [" + jiraVo.getSummary() + "](http://" + config.getIp() + ":" + config.getPort() + "/browse/" + jiraVo.getIssue() + ")\n\n" +
                        "> " + jiraVo.getComment() + "");

                send(jiraVo, markdown);

            }
        }
    }

    public JSONObject getData(HttpServletRequest request) throws IOException {
        BufferedReader reader = request.getReader();
        StringBuilder result = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            result.append(line);
        }
        //打印得到的结果
        return JSONObject.parseObject(result.toString());
    }

    public void sendComment(HttpServletRequest request) throws IOException {
        JSONObject data = getData(request);
        System.err.println(data);
        assert data != null;
        JiraVo jiraVo = new JiraVo();
        jiraVo.setWebhookEvent(data.getString("webhookEvent"));
        jiraVo.setComment(data.getJSONObject("comment").getString("body"));
        jiraVo.setName(data.getJSONObject("comment").getJSONObject("updateAuthor").getString("displayName"));

        //先得到comment的网址
        String self = data.getJSONObject("comment").getString("self");
        String url = StringUtils.substringBefore(self, "/comment");
        try {
            String username = config.getUsername();
            String password = config.getPassword();
            
            HttpResponse<JsonNode> response = Unirest.get(url)
                    .basicAuth(username, password)
                    .header("Accept", "application/json")
                    .asJson();
            JsonNode body = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(body.toString());

            jiraVo.setIssue(jsonObject.getString("key"));
            jiraVo.setSummary(jsonObject.getJSONObject("fields").getString("summary"));
            jiraVo.setProjectName(jsonObject.getJSONObject("fields").getJSONObject("project").get("name").toString());
            jiraVo.setProjectKey(jsonObject.getJSONObject("fields").getJSONObject("project").get("key").toString());
        } catch (UnirestException e) {
            e.printStackTrace();
        }
        
        List<String > userNames = subUser(jiraVo.getComment());
        //查询需要艾特的人
        Map<String, String> atMap = userMapper.selectList(new LambdaQueryWrapper<User>()
                .in(User::getName, userNames)).stream().collect(Collectors.toMap(User::getName, User::getPhone));

        List<String> userPhone= new ArrayList<>();
        for (String userName : userNames) {
            userPhone.add(atMap.get(userName));
        }
        
        
        //处理comment
        String comment = jiraVo.getComment();
        comment = replaceData(comment,atMap);
        
        //markdown
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("jira机器人");
        markdown.setText("#### " + jiraVo.getName() + "  " + jiraVo.getWebhookEvent() + "  " + jiraVo.getIssue() + "\n" +
                "> [" + jiraVo.getSummary() + "](http://" + config.getIp() + ":" + config.getPort() + "/browse/" + jiraVo.getIssue() + ")\n\n" +
                "> " + comment + "");
        sendDing(markdown,userPhone);
    }

    private String replaceData(String comment, Map<String,String> atMap) {
        for (String s : atMap.keySet()) {
             comment = comment.replace("[~" + s + "]", "@" + atMap.get(s));
        }
        return comment;
    }

    private void sendDing(OapiRobotSendRequest.Markdown markdown, List<String> userPhone) {
        //获取 sgin
        Long timestamp = System.currentTimeMillis();
        String stringToSign = timestamp + "\n" + config.getSecret();
        Mac mac;
        String sign = null;
        try {
            mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(config.getSecret().getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
            sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        DingTalkClient client = new DefaultDingTalkClient(config.getServerUrl() + "&timestamp=" + timestamp + "&sign=" + sign);
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        request.setMarkdown(markdown);
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        at.setAtMobiles(userPhone);
        request.setAt(at);
        try {
            client.execute(request);
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }

    //是否艾特人
    private List<String> subUser(String comment) {
        List<String> users = new ArrayList<>();
        if (comment.contains("[~")){
            int i = comment.indexOf("[~");
            String substring = comment.substring(i+2);
            int i1 = substring.indexOf("]");
            String user = substring.substring(0,i1);
            users.add(user);
            users.addAll(subUser(substring));
        }
        return users;
    }


    private void send(JiraVo jiraVo, OapiRobotSendRequest.Markdown markdown) {
        //处理项目名称
        List<String> projectNames = new ArrayList<>();
        String projectNames1 = config.getProjectNames();
        String[] split = projectNames1.split(",");
        Collections.addAll(projectNames, split);

        if (projectNames.contains(jiraVo.getProjectName()) || projectNames.contains(jiraVo.getProjectKey())) {
            //获取sgin
            Long timestamp = System.currentTimeMillis();
            String stringToSign = timestamp + "\n" + config.getSecret();
            Mac mac = null;
            String sign = null;
            try {
                mac = Mac.getInstance("HmacSHA256");
                mac.init(new SecretKeySpec(config.getSecret().getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
                byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
                sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
            } catch (Exception e) {
                e.printStackTrace();
            }

            DingTalkClient client = new DefaultDingTalkClient(config.getServerUrl() + "&timestamp=" + timestamp + "&sign=" + sign);
            OapiRobotSendRequest request = new OapiRobotSendRequest();
            request.setMsgtype("markdown");
            request.setMarkdown(markdown);
            OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
            at.setAtMobiles(Collections.singletonList("18683789032"));
            // isAtAll类型如果不为Boolean，请升级至最新SDK
            at.setIsAtAll(false);
            request.setAt(at);
            try {
                OapiRobotSendResponse response = client.execute(request);
            } catch (ApiException e) {
                e.printStackTrace();
            }
        }

    }
}
